package com.xneure.database.define.resolver;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.dom4j.Element;
import org.dom4j.tree.DefaultAttribute;
import com.xneure.database.define.ColumnDefineImpl;
import com.xneure.database.define.TableDefine;
import com.xneure.database.define.TableDefineImpl;
import com.xneure.database.define.handler.FileTypeHandler;
import com.xneure.database.define.handler.TypeHandler;
import com.xneure.utils.SpringUtil;
import com.xneure.utils.bean.BeanProcessor;
import com.xneure.utils.bean.ClassProperty;
import com.xneure.utils.formatfile.XMLObject;

public class XmlMapResolver implements MapResolver{
	private TableDefine[] defines;

	public XmlMapResolver(){
	}

	public XmlMapResolver(InputStream resourceStream){
		load(resourceStream);
	}

	@SuppressWarnings({"unchecked","rawtypes"})
	@Override
	public void load(InputStream iStream){
		XMLObject xml = new XMLObject();
		xml.ReadData(iStream);
		List<Element> tabels = xml.getElements("/tables/table");
		if(tabels.size() > 0){
			Map<String,TypeHandler> handlers = SpringUtil.getBeanByCls(TypeHandler.class);
			Collection<TypeHandler> h;
			if(null == handlers){
				h = new ArrayList<TypeHandler>(1);
			}else{
				h = handlers.values();
			}
			h.add(new FileTypeHandler());
			defines = new TableDefine[tabels.size()];
			int n = 0;
			for(Element ele:tabels){
				TableDefineImpl td = new TableDefineImpl();
				defines[n++] = td;
				loadProperty(ele.attributes(),h,td);
				List<?> cols = ele.selectNodes("column");
				for(Object col:cols){
					ColumnDefineImpl cd = new ColumnDefineImpl();
					Element _col = (Element)col;
					loadProperty(_col.attributes(),h,cd);
					List c = _col.selectNodes("defaultValue | comment");
					if(c.size() > 0){
						Map<String,ClassProperty> beanInfo = BeanProcessor.getBeanInfo(cd.getClass());
						c.forEach(e-> {
							Element element = (Element)e;
							ClassProperty classProperty = beanInfo.get(element.getName());
							if(null != classProperty){
								for(TypeHandler tmp:h){
									if(tmp.support(classProperty.getType())){
										Object res = tmp.handler(cd,element.getName(),element.getStringValue(),classProperty.getType());
										tmp.propertyHandler(classProperty,cd,res);
										break;
									}
								}
							}
						});
					}
					td.addColumn(cd);
				}
			}
		}
	}

	@SuppressWarnings({"unchecked","rawtypes"})
	private void loadProperty(List<?> cols,Collection<TypeHandler> h,Object _obj){
		Map<String,ClassProperty> beanInfo = BeanProcessor.getBeanInfo(_obj.getClass());
		cols.forEach(ele-> {
			DefaultAttribute o = (DefaultAttribute)ele;
			ClassProperty classProperty = beanInfo.get(o.getName());
			if(null != classProperty){
				for(TypeHandler tmp:h){
					if(tmp.support(classProperty.getType())){
						Object res = tmp.handler(_obj,o.getName(),o.getValue(),classProperty.getType());
						tmp.propertyHandler(classProperty,_obj,res);
						break;
					}
				}
			}
		});
	}

	@Override
	public TableDefine[] getTableDefines(){
		return defines;
	}
}
